package com.ruoyi.scale.service;

import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.json.JsonUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.scale.assembler.ScaleLogAssembler;
import com.ruoyi.scale.document.Scale;
import com.ruoyi.scale.document.ScaleLog;
import com.ruoyi.scale.document.base.BaseDocumentService;
import com.ruoyi.scale.document.refs.ScaleAnswer;
import com.ruoyi.scale.document.refs.ScaleResult;
import com.ruoyi.scale.rule.EvalRule;
import com.ruoyi.scale.vo.AnswerScaleVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Slf4j
@Service
public class ScaleLogService extends BaseDocumentService<ScaleLog> {
    private Map<String,Class> clazzMap = new HashMap<>();

    @Resource
    private ScaleService scaleService;
    @Resource
    private ScaleLogAssembler scaleLogAssembler;
    /**
     * 回答
     * @param answerScaleVo
     * @return
     */
    public ScaleLog answer(AnswerScaleVo answerScaleVo){
        //校验答案
        checkAnswer(answerScaleVo);
        //
        Scale scale = new Scale();
        scale.setCode(answerScaleVo.getScaleCode());
        List<Scale> scales = scaleService.findAll(Example.of(scale));
        if(scales.size() < 1){
            throw new IllegalArgumentException("无效量表编码!");
        }
        if(scales.size() > 1){
            throw new IllegalArgumentException("量表编码关联多个量表配置:" + answerScaleVo.getScaleCode());
        }
        scale = scales.get(0);
        ScaleLog scaleLog = scaleLogAssembler.buildScaleLog(answerScaleVo);
        //
        scaleLog.setScaleId(scale.getId());
        scaleLog.setScaleName(scale.getName());
        scaleLog.setReportShowComponent(scale.getReportShowComponent());
        //解析特殊表单数据
        parseFormData(answerScaleVo, scaleLog, scale);
        //获取执行器
        EvalRule evalRule = SpringUtils.getBean(scale.getRuleName());
        //执行器准备动作
        evalRule.prepare(scaleLog);
        //开始执行结果
        ScaleResult scaleResult = evalRule.eval(scale, scaleLog);
        scaleLog.setResult(scaleResult);
        //结果保存
        scaleLog.setAnswerTime(new Date());
        ScaleLog poScaleLog = this.save(scaleLog);
        return poScaleLog;
    }

    private void parseFormData(AnswerScaleVo answerScaleVo, ScaleLog scaleLog, Scale scale) {
        if (StringUtils.isNotBlank(scale.getInputFormClass())
                && StringUtils.isNotEmpty(answerScaleVo.getForm())) {
            scaleLog.setFormData(
                    JsonUtils.deserialize(answerScaleVo.getForm()
                            ,loadClass(scale.getInputFormClass()))
            );
        }
    }

    private Class loadClass(String className){
        Class aClass = clazzMap.get(className);
        if(aClass == null){
            try {
                aClass = Class.forName(className);
            }catch (Exception e){
                log.error("加载接收参数类失败!",e);
                throw new IllegalArgumentException(e);
            }
            clazzMap.put(className,aClass);
        }
        return aClass;
    }

    private void checkAnswer(AnswerScaleVo scaleLog) {
        for (ScaleAnswer scaleAnswer : scaleLog.getAnswerList()) {
            //验证 TODO
        }
    }
}
